using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using dpa.Library.Models;
using dpa.Library.Services;

namespace dpa.Library.ViewModels;

public partial class FavoriteViewModel : ViewModelBase//, IRecipient<FavoriteStorageUpdatedMessage>
{
    private readonly IFavoriteStorage _favoriteStorage;

    private readonly IPoetryStorage _poetryStorage;

    private readonly IContentNavigationService _contentNavigationService;

    public FavoriteViewModel(IFavoriteStorage favoriteStorage,
        IPoetryStorage poetryStorage,
        IContentNavigationService contentNavigationService)
    {
        _favoriteStorage = favoriteStorage;
        _poetryStorage = poetryStorage;
        _contentNavigationService = contentNavigationService;

        //广播消息
        //WeakReferenceMessenger.Default.Register(this);
        //事件方法
        _favoriteStorage.Updated += FavoriteStorageOnUpdated;
    }

    private ObservableCollection<PoetryFavorite> PoetryFavoriteCollection { get; } = new();

    [ObservableProperty] private bool _isLoading;

    private bool _isLoaded;

    [RelayCommand]
    private async Task OnInitializedAsync()
    {
        if (_isLoaded)
        {
            return;
        }

        IsLoading = true;

        PoetryFavoriteCollection.Clear();
        var favoriteList = await _favoriteStorage.GetFavoritesAsync();

        // List<PoetryFavorite> poetryFavorites = (await Task.WhenAll(
        //     favoriteList.Select(p => Task.Run(async () => new PoetryFavorite
        //     {
        //         Poetry = await _poetryStorage.GetPoetryAsync(p.PoetryId), Favorite = p
        //     })))).ToList();
        
        // 原始代码的异步 LINQ 版本
        var poetryFavorites = await favoriteList
            .ToAsyncEnumerable()          // 将集合转换为异步枚举
            .SelectAwait(async p =>       // 使用异步 Select
                new PoetryFavorite 
                {
                    Poetry = await _poetryStorage.GetPoetryAsync(p.PoetryId),
                    Favorite = p
                })
            .ToListAsync(); 

        poetryFavorites.ForEach(f => PoetryFavoriteCollection.Add(f));

        //PoetryFavoriteCollection.AddRange(poetryFavorites);

        IsLoading = false;
    }

    [RelayCommand]
    private void ShowPoetry(Poetry poetry) =>
        _contentNavigationService.NavigateTo(ContentNavigationConstant.DetailView, poetry);

    private async void FavoriteStorageOnUpdated(object sender,
        FavoriteStorageUpdatedEventArgs e)
    {
        var favorite = e.UpdatedFavorite;
        PoetryFavoriteCollection.Remove(
            PoetryFavoriteCollection.FirstOrDefault(p =>
                p.Favorite.PoetryId == favorite.PoetryId));

        if (!favorite.IsFavorite)
        {
            return;
        }

        var poetryFavorite = new PoetryFavorite
        {
            Poetry = await _poetryStorage.GetPoetryAsync(favorite.PoetryId), Favorite = favorite
        };

        var index = PoetryFavoriteCollection.IndexOf(
            PoetryFavoriteCollection.FirstOrDefault(p =>
                p.Favorite.Timestamp < favorite.Timestamp));
        if (index < 0)
        {
            index = PoetryFavoriteCollection.Count;
        }

        PoetryFavoriteCollection.Insert(index, poetryFavorite);
    }

    public async void Receive(FavoriteStorageUpdatedMessage message)
    {
        var favorite = message.Value;
        PoetryFavoriteCollection.Remove(
            PoetryFavoriteCollection.FirstOrDefault(p =>
                p.Favorite.PoetryId == favorite.PoetryId));

        if (!favorite.IsFavorite)
        {
            return;
        }

        var poetryFavorite = new PoetryFavorite
        {
            Poetry = await _poetryStorage.GetPoetryAsync(favorite.PoetryId), Favorite = favorite
        };

        var index = PoetryFavoriteCollection.IndexOf(
            PoetryFavoriteCollection.FirstOrDefault(p =>
                p.Favorite.Timestamp < favorite.Timestamp));
        if (index < 0)
        {
            index = PoetryFavoriteCollection.Count;
        }

        PoetryFavoriteCollection.Insert(index, poetryFavorite);
    }
}